package moon.core.expression;

import moon.core.ObjectMoon;
import moon.core.classdef.Type;
import moon.traverse.Visitor;


/** 
 * An expression is a computation returning an object: entity, call expression or manifest constant.
 * 
 * In Moon, methods linked to processes are routines, while messages with information
 * are associated with attributes and functions.
 * 
 * All messages are associated to an entity, an expression (using an attribute or function) or a routine
 * with an instruction.
 *
 * @author <a href="mailto:rmartico@ubu.es">Ra&uacute;l Marticorena</a>
 */
@SuppressWarnings("serial")
public abstract class Expr extends ObjectMoon {
			
    /** 
     * Type of the expression.
     */    
    private Type type;
    
    /** 
     * Constructor.
     * 
     * @param type type
     */
    public Expr(Type type) {
        super();
        this.setType(type);
    }
    
    /** 
     * Sets the type of this expression.
     * 
     * @param pType type
     * @see #getType
     */    
    public void setType(Type pType){
        this.type = pType;
    }
    
    /** 
     * Gets the type of the expression.
     * 
     * @return type
     * @see #setType
     */    
    public Type getType(){
    	if (this.hasCastType()){
    		return this.getCastType();
    	}
        return this.type;
    }
    
	/**
     * Method from Pattern Design Visitor.
     * By RMS.
     * 
     * @param visitor visitor
     */
    public void accept(Visitor visitor){
    	// Hook method
    	visitor.visit(this);
    }
    
    /**
     * Gets if the expression is a constant.
     * 
     * @return true if it is a constant, false in other case
     */
    public abstract boolean isConstant();
    
   
    /**
     * Gets if the expression creates a new object.
     * 
     * @return true if it is a creation expression, false in other case
     */
    public abstract boolean isCreation();
    

    /**
     * Cast type.
     */
	private Type castType; 
	
	
	/**
	 * Sets the cast.
	 * 
	 * @param type type cast
	 */
	public void setCastType(Type type) {
		castType = type;
	}
	
	/**
	 * Gets cast type.
	 * 
	 * @return cast type
	 */
	public Type getCastType() {
		return castType;		
	}
	
	/**
	 * Gets if the expression has a cast type.
	 * 
	 * @return true if it has a cast, false in other case
	 */
	public boolean hasCastType() {
		return castType!=null;
	}
	
	
	/**
	 * Gets the type of the expression without the cast.
	 * 
	 * @return type witout cast
	 */
	public Type getTypeWithoutCast() {
		return type;		
	}
} // Expr
